package com.hempton.flexmarkers;

import java.util.HashMap;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.Path;
import org.eclipse.jface.text.BadLocationException;
import org.eclipse.jface.text.IDocument;
import org.eclipse.ui.console.IPatternMatchListenerDelegate;
import org.eclipse.ui.console.PatternMatchEvent;
import org.eclipse.ui.console.TextConsole;

/**
 * Matches relevant flex compiler (mxmlc or compc) compiler output
 * and generates corresponding error/warning markers
 * @author ghempton
 *
 */
public class FlexPatternMatcher implements
		IPatternMatchListenerDelegate {

	/*
	 * Example Compiler Output Cases:
	 * 
 	 * a) [compc] Warning: Source path entry, 'C:\Users\ghempton\oakland\branches\refactor\common\resources\locale\en_US', is a subdirectory of source path entry, 'C:\Users\ghempton\oakland\branches\refactor\common\resources'.
   	 * b) [compc] C:\Users\ghempton\oakland\branches\refactor\common\flex_src\com\designbyparts\oakland\common\errors\OaklandError.as(10): col: 21 Error: Type was not found or was not a compile-time constant: Strin.
	 * c) [mxmlc] C:\Users\ghempton\oakland\branches\refactor\site\flex_src\site.mxml: Error: Could not resolve <oakland:Oaklan> to a component implementation.
	 * d) [mxmlc] Error: unable to open 'C:\Users\ghempton\workspaces\plugin\flexmarkers_test\src/testapp.error.mxml'
	 * 
	 * Regexp:
	 * \[(mxmlc|compc)\] (.?.?[^\(\):]*)\(?(\d*)\)?[^\d]*(\d*)[^\d]*(Error|Warning): (.*)
	 * 
	 * This regular expression should match the error/warning messages
	 * to the following matcher groups
	 * 
	 * 1: Compiler type (mxmlc or compc)
	 * 2: File name
	 * 3: Line number
	 * 4: Column number
	 * 5: Type (Error or Warning)
	 * 6: Message
	 */
	private static final Pattern pattern = Pattern.compile("\\[(mxmlc|compc)\\] (.?.?[^\\(\\):]*)\\(?(\\d*)\\)?[^\\d]*(\\d*)[^\\d]*(Error|Warning): (.*)");
	
	private TextConsole console;
	
	// TODO: we should share the same instance of the marker manager
	// throughout the plugin
	private FlexMarkerManager markerManager = new FlexMarkerManager();
	
	// Caches IFile objects for faster retrieval
	private Map<String, IFile> fileCache = new HashMap<String, IFile>();
	
	@Override
	public void connect(TextConsole console) {
		this.console = console;
	}

	@Override
	public void disconnect() {
	}

	@Override
	public void matchFound(PatternMatchEvent event) {
		String line = getMatchedText(event);
		Matcher matcher = pattern.matcher(line);
		
		if(!matcher.find()) {
			return;
		}
		
		IFile file = getIFile(matcher.group(2));
		Integer lineNumber = matcher.group(3).equals("") ? null : Integer.parseInt(matcher.group(3));
		Integer columnNumber = matcher.group(4).equals("") ? null : Integer.parseInt(matcher.group(4));
		boolean isError = matcher.group(5).equals("Error");
		String message = matcher.group(6);
		
		markerManager.addMarker(file, lineNumber, columnNumber, isError, message);
		
		// TODO: Add hyperlinks
	}
	
	protected String getMatchedText(PatternMatchEvent event) {
		int eventOffset= event.getOffset();
		int eventLength= event.getLength();
		IDocument document= console.getDocument();
		String matchedText= null;
		try {
			matchedText= document.get(eventOffset, eventLength);
		} catch (BadLocationException e) {
			// TODO: look into logging api
			e.printStackTrace();
		}
		return matchedText;
	}
	
    protected IFile getIFile(String filePath) {
        if (filePath == null || filePath.equals("")) {
            return null; 
        }
        IFile file= fileCache.get(filePath);
        if (file == null) {
            IFile[] files = ResourcesPlugin.getWorkspace().getRoot().findFilesForLocation(new Path(filePath));
            if (files.length > 0) {
                file = files[0];
                fileCache.put(filePath, file);
            }
        }
        return file;
    }

}
